home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # Apple Developer Technical Support
- #
- # AEDeamon
- # A small faceless background-only application
- #
- # AEDeamonPPCStuff.c - C Source
- #
- # Copyright © 1991 Apple Computer, Inc.
- # All rights reserved.
- #
- # Versions:
- # 1.0 08/91 C.K. Haun <TR>
- #
- # Components:
- # AEDeamonMain.c
- # AEDeamonAEvents.c
- # AEDeamonPPCStuff.c
- --------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- # This file contains all the PPC stuff for the AEDeamon. It reads the AppleEvent
- # data from the PPC channel, puts it in an AEDesc, and fires it for AESend.
- # That's all it does. But _not_ all it could do. If the sender wanted a reply,
- # the Deamon could send the reply back through the same channel the event came through.
- # This sample does the minimum, but you can expand it reasonably easily to
- # give full AppleEvent support to any DA/INIT/CDEV/DRIVER you want.
- --------------------------------------------------------------------------------*/
-
-
- #include "AEDaemon.h"
-
-
- Handle dataHandle;
- OSType gTypeTag;
- Boolean gMore;
- PPCPortRec ourPort;
- PPCPortRefNum ourPortID;
- MyPPCRecPtrDeamon ourPPCPtr;
- PPCPortRec myPortName;
- LocationNameRec myLoc;
- Ptr readBuffer;
- Handle eventData;
- #define kGenStrings 128
- #define kPortName 132
- extern Boolean gReadPending;
- extern unsigned long gMySleep;
-
- /* InformTheWorld opens our PPC port, and posts a PPCInform so other folks */
- /* can connect to us */
- Boolean InformTheWorld(void)
- {
- Boolean result = false;
-
- OSErr myErr = noErr;
- PPCOpenPBPtr localPtr;
- localPtr = (PPCOpenPBPtr)ourPPCPtr; /* makes things more readable */
- /* get a buffer to read stuff into */
- /* first get a port, if we don't already have one */
- if (ourPortID == nil) {
- myErr = OpenAPort((PPCOpenPBPtr)ourPPCPtr);
- if (myErr)
- return(false); /* we failed, die */
-
- ourPortID = localPtr->portRefNum;
- }
- DoInform((PPCInformPBPtr)ourPPCPtr);
-
- return(result);
- }
-
- /* OpenAPort, uhhh, opens a port. Opens our PPC port for others */
- /* to talk to us through */
- OSErr OpenAPort(PPCOpenPBPtr myPort)
- {
- myPortName.nameScript = 0;
- GetIndString(&myPortName.name,kGenStrings,kPortName);
- myPortName.portKindSelector = ppcByCreatorAndType;
- myPortName.u.port.creator = 'MOOB';
- myPortName.u.port.type = 'APPL';
- myPort->ioCompletion = (PPCCompProcPtr)OpenComplete;
-
- myPort->serviceType = ppcServiceRealTime; /* only valid one under 7.0 */
- myPort->resFlag = 0;
- myPort->portName = &myPortName;
- myPort->locationName = &myLoc;
- myPort->networkVisible = false; /* NO, I don't want others using this service */
- myLoc.locationKindSelector = ppcNoLocation;
-
- /* open syncrnouls */
- return(PPCOpen(myPort, true));
-
- }
-
- /* PPCOpenPort */
-
- /* DoInform posts a PPCInform, telling the world that we are ready to */
- /* accept data through our PPC channel */
- Boolean DoInform(PPCInformPBPtr p)
- {
-
- p->ioCompletion = (PPCCompProcPtr)InformComplete;
- /* port reference number is already set in the Parameter Block */
- /* most of this junk is already set */
- p->portName = nil;
- p->locationName = nil;
- p->userName = nil;
- p->autoAccept = true; /* if true session will be accepted automatically */
- /* instead of having to go through a PPCAccept. I'm doing this primarly */
- /* because this deamon is not network visible, so I don't thing anyone */
- /* will be playing hijinks on us. */
- if (PPCInform(p, true) != noErr) {
- return false;
- } else
- return true;
- }
-
- /* DoInform */
-
- /* CloseOffTheWorld shuts things down when this app quits */
- void CloseOffTheWorld(void)
- {
- PPCClosePBPtr closeRec = NewPtrClear(sizeof(PPCClosePBRec));
- closeRec->ioCompletion = nil;
- closeRec->ioResult = 0;
- closeRec->portRefNum = ourPortID;
- PPCClose(closeRec, false);
- DisposPtr((Ptr)closeRec);
-
-
- }
-
- /* I could post the PPC inform from here, but I decided not to in this case. */
- /* Why? I'm not sure. */
- void OpenComplete(PPCInformPBPtr p)
- {
- #pragma unused (p)
- /* do nothing */
-
- }
-
- /* When this InformCompletion routine is hit, that means that someone has */
- /* invoked a PPCStart on our port. Since we automatically accepted it, we */
- /* will begin reading from here. If we wanted to authenticate, we'd do a PPCAccept */
- /* here (if we wanted to accept) and then start the read from the */
- /* PPCAccept completion routine. */
- void InformComplete(PPCReadPBPtr p)
- {
- /* Start reading Bucky */
-
- p->ioCompletion = (PPCCompProcPtr)ReadComplete;
- p->bufferPtr = readBuffer;
- p->bufferLength = kOneK;
- gMySleep = 1; /* bump the sleep time down so we can start processing faster */
- /* so we can process the data after it's read */
- /* since we won't go through WaitNextEvent and see the completion flag unless */
- /* we bump the sleep time down a bit */
- PPCRead((PPCReadPBPtr)p, true);
- }
-
- /* When we hit this completion routine, it means one of two things; */
- /* 1) We are all done reading, and we are ready to send the event */
- /* or */
- /* 2) We've filled our PPC buffer (rememeber, it was only one K ) */
- /* and we need to swap that data to a safe place and read again */
- void ReadComplete(PPCReadPBPtr p)
- {
- /* read completeed, deal with it */
- gReadPending = true;
- gMore = p->more;
- gTypeTag = p->blockType;
- gMySleep = 0;
- }
-
- /* this processes the result of the last async read, and re-reads if */
- /* theres more data to get */
- /* It also checks to see if this is data we understand. In this case, MAVT type */
- /* data (which means My AppleeVenT), I set this type in the PPCWrite block */
- /* elsewhere. If you don't do this, bad things will happen when you try */
- /* and do an AESend on data someone else sent */
- void CollectLastData(void)
- {
- unsigned long currentSize;
- AppleEvent theEvent;
- PPCReadPBPtr localPtr = (PPCReadPBPtr)ourPPCPtr;
- if (gMore) {
- /* we need to move the current data into another buffer, and then read again */
- currentSize = GetHandleSize(dataHandle);
- SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
- HLock(dataHandle);
- BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
- HUnlock(dataHandle);
- localPtr->ioCompletion = (PPCCompProcPtr)ReadComplete;
- localPtr->bufferPtr = readBuffer;
- localPtr->bufferLength = kOneK;
- /* read more */
- PPCRead((PPCReadPBPtr)localPtr, true);
-
- } else {
- /* now we need to send the thing. So send it, then re-post the inform */
- /* there's no more, but we need to move what we have */
- /* same as before */
- if (gTypeTag == kMyTypeOfData) {
- currentSize = GetHandleSize(dataHandle);
- SetHandleSize(dataHandle, currentSize + localPtr->actualLength);
- HLock(dataHandle);
- BlockMove(readBuffer, (*dataHandle) + currentSize, localPtr->actualLength);
- HUnlock(dataHandle);
-
- PPCEnd((PPCEndPBPtr)localPtr, false);
-
- gReadPending = false;
- gMySleep = 200; /* back to sleep */
- /* now send the event we've so laboriously xfered */
- /* you'll notice here that I am setting the descriptor type */
- /* to 'aevt' and using some default interaction, reply, and */
- /* timeout values. To be more flexible, you should pass all these paramters */
- /* as a 'header' block through PPC, see the Read Me file for more details */
- /* I am doing this here for simpliciites sake */
- theEvent.descriptorType = kCoreEventClass;
- theEvent.dataHandle = dataHandle;
- AESend(&theEvent, nil, kAECanInteract + kAENoReply + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,
- nil, nil);
- /* so we just sent the event. Normally, you'd call AEDisposeDesc on this thing, */
- /* but in this case since it's our handle made by us, I'll just set it's size */
- /* back to zero */
- } else {
- /* it was not my data type, so end the session */
- PPCEnd((PPCEndPBPtr)localPtr, false);
- }
- SetHandleSize(dataHandle, 0);
- /* Now we re-inform, we're ready for another message */
- InformTheWorld();
- }
- }
-
-
-